package com.ceba.test.base.sign.helper;

import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;

import com.ceba.base.enums.AbcSignTypeEnum;
import com.ceba.base.helper.LoggerHelper;
import com.ceba.base.sign.enums.ErrSign;
import com.ceba.base.utils.PDFUtils;
import com.ceba.base.verify.CertUtils;
import com.ceba.base.verify.entity.CertInfo;
import com.ceba.cebacer.KeyLoaderType;
import com.ceba.cebautils.DateUtil;
import com.ceba.cpdf.bean.SignCertParam;
import com.ceba.cpdf.key.KeyLoader;
import com.ceba.forpdf.pdf.PdfTools;
import com.ceba.test.base.helper.SystemHelper;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ceba.forpdf.pdf.CertificationUtils;
import com.ceba.key.cache.KeyCerCache;
import com.ceba.key.utils.KeyUtils;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.language.ResourceUtils;

import abc.certificate.PrivateKeyAndCertificationChain;
import abc.util.StringUtils;

public class CheckSignHelper {

	private static Logger logger = LoggerFactory.getLogger(CheckSignHelper.class);

	/**
	 * 当前这个证书是否可以用于这个系统进行签名
	 * @return 0成功，1无法获取证书链，
	 * 2证书过期,3签名企业和初始设置不符
	 * 4签名报告与统计份数不一致
	 * 5无法签名，未激活数字证书签名
	 * 6超过允许签名的份数
	 * @throws Exception
	 */
	private static String checkAllowSign() throws Exception{
		X509Certificate needCer = null;
	    if(AbcSignTypeEnum.File.getCode().equals(SystemHelper.getAbcSignKeyType())){
			try {
				needCer = PDFUtils.getSignCerParam(KeyLoaderType.TYPE_P12);
				if (needCer == null) {
					logger.debug(ErrSign.ERR_1.getValue());
					return ErrSign.ERR_1.getCode() + "";
				}
			} catch (Exception e) {
				logger.debug(ErrSign.ERR_1.getValue());
				LoggerHelper.error(logger, e, "");
				return ErrSign.ERR_1.getCode() + "";
			}
		}else {
			SignCertParam signCertParam = KeyLoader.getInstance().getCertFromKey(CebaConfig.SIGN_COMPANY);
			if (signCertParam != null && signCertParam.getCert() !=null && signCertParam.getPk() !=null) {
				String cert = Base64.encodeBase64String(signCertParam.getCert());
				CertInfo certInfo = CertUtils.getCertInfoFromSignCert(cert);
				if (certInfo != null) {
					needCer = certInfo.getX509Certificate();
				}else{
					logger.debug(ErrSign.ERR_1.getValue());
					return ErrSign.ERR_1.getCode() + "";
				}
			}else{
				if (null == signCertParam) {
					logger.debug("signCertParam is null");
				}

				logger.debug(ErrSign.ERR_1.getValue());
				return ErrSign.ERR_1.getCode() + "";
			}
		}
	    KeyCerCache.cer = needCer;

	    String signCompany= KeyUtils.parseCertDN(needCer.getSubjectDN().toString().toLowerCase(),"cn");
	    SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");
	    String cerSignValidity=df.format(needCer.getNotAfter());
	    String signValidity = CebaConfig.SIGN_VALIDITY;
	    if(StringUtils.isNullOrEmpty(signValidity)){
	    	//如果不存在，就加密值，并把它存在配置中
	    	CebaConfig.set("SIGN_VALIDITY", cerSignValidity);
	    	signValidity = cerSignValidity;
	    }
	    //先判断证书的日期是否已经真正过期
	    int i = DateUtil.compareDate(cerSignValidity, DateUtil.getNowTime("yyyy-MM-dd"), "yyyy-MM-dd");
	    if(i==2){
	    	logger.debug(ErrSign.ERR_2.getValue());
	    	return ErrSign.ERR_2.getCode()+"";
    	}
	    //数据库的证书日期是否过期
	    i=DateUtil.compareDate(signValidity, DateUtil.getNowTime("yyyy-MM-dd"), "yyyy-MM-dd");
    	if(i==2){
    		logger.debug(ErrSign.ERR_2.getValue());
    		return ErrSign.ERR_2.getCode()+"";
    	}

	    if(StringUtils.isNullOrEmpty(CebaConfig.SIGN_COMPANY)){
	    	//如果不存在，就加密值，并把它存在配置中
	    	CebaConfig.set("SIGN_COMPANY", CebaConfig.getEncode(signCompany));
	    }
	    else{
	    	if(!CebaConfig.SIGN_COMPANY.toLowerCase().replace(" ","").equals(signCompany.toLowerCase().replace(" ",""))){
	    		logger.debug(ErrSign.ERR_3.getValue());
	    		return ErrSign.ERR_3.getCode()+"";
	    	}
	    }

	    if(!"true".equals(CebaConfig.SING_COMPANY_ACTIVATE_FLAG)){
	    	logger.debug(ErrSign.ERR_5.getValue());
	    	return ErrSign.ERR_5.getCode()+"";
	    }

		if(SystemHelper.canOnlyAllowShcaKeyFlag()) {
			if (!KeyUtils.checkHasSpecialNode(needCer)) {
				System.out.println(ErrSign.ERR_8.getValue());
				logger.debug(ErrSign.ERR_8.getValue());
				return ErrSign.ERR_8.getCode() + "";
			}
		}
	    return ErrSign.ERR_0.getCode()+"";
	}


	/**
	 * 判断能否签名
	 * @return
	 */
	public static JSONObject checkCanSign() throws Exception{
		JSONObject r = new JSONObject();
		String checkCode = null;

		JSONObject ob = SystemHelper.checkSystemCanUse("config");
		// 系统未激活，或者系统到期
		if(!(ErrSign.ERR_0.getCode()+"").equals(ob.get("status"))){
			logger.error(ob.getString("message"));
			checkCode = String.valueOf(ob.getInt("status"));
			r.put("status", checkCode);
			r.put("message", ResourceUtils.getMessage(ErrSign.getLanguageFlag(Integer.valueOf(checkCode))));
			return r;
		}
		// 按签名文档份数收费，而且当前系统剩余可用份数为0
		if("1".equals(CebaConfig.SYSTEM_FEE_TYPE) && !SystemHelper.isSystemHasLeftSignCount()){
			logger.error(ErrSign.ERR_6.getValue());
			checkCode = String.valueOf(ob.getInt("status"));
			r.put("status", checkCode);
			r.put("message", ResourceUtils.getMessage(ErrSign.getLanguageFlag(Integer.valueOf(checkCode))));
			return r;
		}

		// 判断签名类型
		PdfTools.checkSignType(SystemHelper.getAbcSignKeyType(), 0);
		if(SystemHelper.canChooseServerSignFlow()){
			r.put("status", ErrSign.ERR_0.getCode()+"");
			r.put("message", "");
			return r;
		}

		checkCode = checkAllowSign();
		if(!(ErrSign.ERR_0.getCode()+"").equals(checkCode)){
			r.put("status", checkCode);
			r.put("message", ResourceUtils.getMessage(ErrSign.getLanguageFlag(Integer.valueOf(checkCode))));
		}else if(ErrSign.ERR_8.equals(checkCode)){
			r.put("status",checkCode);
			r.put("message", "");
		}else {
			r.put("status", checkCode);
			r.put("message", "");
		}
		return r;
	}

	/**
	 * 签名过程中的判断是否还有特殊节点
	 * @return
	 * @throws Exception
	 */
	public static String checkHasSpecialNode() throws Exception{
		 if(KeyCerCache.cer == null){
			return checkAllowSign();
		 }
		 if(!KeyUtils.checkHasSpecialNode(KeyCerCache.cer)){
	    	logger.debug(ErrSign.ERR_8.getValue());
	    	return ErrSign.ERR_8.getCode()+"";
		 }
		 return ErrSign.ERR_0.getCode()+"";
	}


}
